package com.itbaizhan.paymentdemo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.itbaizhan.paymentdemo.config.ZfbPayConfig;
import com.itbaizhan.paymentdemo.entity.OrderInfo;
import com.itbaizhan.paymentdemo.entity.PaymentInfo;
import com.itbaizhan.paymentdemo.entity.RefundInfo;
import com.itbaizhan.paymentdemo.enums.OrderStatus;
import com.itbaizhan.paymentdemo.enums.PayType;
import com.itbaizhan.paymentdemo.enums.zfb.ZfbNotifyType;
import com.itbaizhan.paymentdemo.service.IOrderInfoService;
import com.itbaizhan.paymentdemo.service.IPaymentInfoService;
import com.itbaizhan.paymentdemo.service.IRefundInfoService;
import com.itbaizhan.paymentdemo.service.IZfbPayService;
import com.itbaizhan.paymentdemo.vo.BaseResult;
import com.itbaizhan.paymentdemo.vo.CodeEnum;
import com.itbaizhan.paymentdemo.vo.PayInfoVo;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

//支付宝业务层
@Service
@Slf4j
public class ZfbPayServiceImpl implements IZfbPayService {
    @Autowired
    private IOrderInfoService iOrderInfoService; //订单

    @Autowired
    private IPaymentInfoService iPaymentInfoService; //交易

    @Autowired
    private IRefundInfoService iRefundInfoService;//退款
    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private ZfbPayConfig zfbPayConfig;
    //统一下单  ,将本地的请求参数发送给支付宝，返回二维码地址
    @Override
    public BaseResult pcPay(String orderNo) {

        //查找订单
        OrderInfo orderInfo = iOrderInfoService.findByOrderNo(orderNo);
        // 2. 判断订单是否存在,不存在抛出异常
        if(orderInfo == null){
            return BaseResult.error(CodeEnum.ORDER_ERROR);
        }

        //封装请求参数
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        // 3. 支付请求参数拼接
        JSONObject bizContent = new JSONObject();
        //商户订单号
        bizContent.put("out_trade_no",orderNo);
        //支付金额
        bizContent.put("total_amount",orderInfo.getTotalFee());
        //订单标题
        bizContent.put("subject",orderInfo.getTitle());
        //商户门店编号
        bizContent.put("store_id","00100");
        request.setBizContent(bizContent.toJSONString());//向支付定发送请求
        // 回调函数   将回调的函数设置在这地址
        request.setNotifyUrl(zfbPayConfig.getNotifyUrl().concat(ZfbNotifyType.PC_NOTIFY.getType()));
        AlipayTradePrecreateResponse response = null;
        //支付宝二维码URL
        String qrCode = "";
        try {
            response = alipayClient.execute(request);
            if (!response.isSuccess()) {
                throw new Exception("生成支付宝订单失败:" + response.getMsg() + response.getQrCode());
            }
            qrCode = response.getQrCode(); //请求成功，返回二维码
        } catch (Exception e) {
            e.printStackTrace();
            //throw new Exception(e.getMessage());
        }

        // 封装支付信息 返回
        PayInfoVo payInfoVo = new PayInfoVo();
        payInfoVo.setOrderNo(orderNo);
        payInfoVo.setCodeUrl(qrCode);
        log.info("payInfo: {}",payInfoVo);
        return BaseResult.ok(payInfoVo);
    }

    /**
     * 修改订单状态  支付成功后 订单状态由 未支付变为已支付
     * @param request
     */@Transactional(rollbackFor = Exception.class)
    @Override
    public void updateOrderStatus(HttpServletRequest request) {
            //获得订单，再修改状态   key值是从支付宝开发者平台上查看获得

        //1,从异步通知结果,获得订单状态
        String tradeStatus = request.getParameter("trade_status");

        if (tradeStatus.equals("TRADE_SUCCESS")){
            //获取订单编号，异步获取
            String orderNo = request.getParameter("out_trade_no");
            //从订单编号获取订单数据
            OrderInfo orderInfo = iOrderInfoService.findByOrderNo(orderNo);
            if(!OrderStatus.NOTPAY.getType().equals(orderInfo.getOrderStatus())){
                return;  //如果订单状态不是未支付，就返回
            }
            //修改订单状态
            iOrderInfoService.updateOrderStatus(orderNo, OrderStatus.SUCCESS);

            //添加交易记录
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setOrderNo(orderNo);
            String tradeNo = request.getParameter("trade_no");
            paymentInfo.setTransactionId(tradeNo);//交易号
            paymentInfo.setPaymentType(PayType.ALIPAY.getType());//支付类型
            paymentInfo.setTradeType("当面付");
            paymentInfo.setTradeState(tradeStatus);//交易状态
            paymentInfo.setPayerTotal(orderInfo.getTotalFee());
            paymentInfo.setContent(JSON.toJSONString(request.getParameterMap()));//所有内容
            paymentInfo.setCreateTime(LocalDateTime.now());

            iPaymentInfoService.save(paymentInfo);//保存

        }
    }

    //申请退款
    @Override
    public void refund(String orderNo, String reason) {
        log.info("********支付宝退款********");
        //1,根据创建退款订单
        RefundInfo refundInfo = iRefundInfoService.createRefundByOrderNo(orderNo, reason);
        //2封装参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no",orderNo);//订单编号
        bizContent.put("refund_amount",refundInfo.getRefund());//退款金额

        //3转json存入request
        request.setBizContent(bizContent.toString());
        //4发送请求
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);

            if(response.isSuccess()){
                System.out.println("调用成功");
                //修改订单
                iOrderInfoService.updateOrderStatus(orderNo,OrderStatus.REFUND_SUCCESS);
                //修改退款订状态
                iRefundInfoService.updateRefundAliPayStatus(orderNo);
            }else {
                System.out.println("退款失败");
                log.error("*******调用失败=>{}",response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }


    }

    /**
     * 查询订单状态
     * @param orderNo  订单编号
     * @return
     * 用参数订单编号发送请求，查询状态
     */
    @Override
    public String queryOrderStatus(String orderNo) throws Exception {
        log.info("**********统一交易状态查询*********");
        //1,组装参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no",orderNo);//订单编号
        //3转json存入request
        request.setBizContent(bizContent.toString());
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            log.info("*******查询交易状态调用成功={}",response.getBody());
            return response.getBody();//支付宝返回的数据
        }else {
            log.error("调用失败",response.getBody());
            throw new Exception("查询交易记录失败");
        }

    }
}
